package com.jorado.ognl;

import ognl.Node;
import ognl.Ognl;
import ognl.OgnlException;
import ognl.SimpleNode;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Auther: len.zhang
 * @Date: 2019/8/14 11:09
 * @Description: 表达式节点缓存
 */
public class NodeCache {

    private static final Map<String, CacheData> CACHE = new ConcurrentHashMap<>(200);

    /**
     * 从缓存获取节点，防止重复编译
     *
     * @param expression
     * @return
     */
    public static Node getNode(String expression) throws OgnlException {
        CacheData cacheData = CACHE.get(expression);
        if (cacheData != null) {
            return cacheData.getNode();
        }
        cacheData = registerNode(expression);
        if (cacheData != null) {
            return cacheData.getNode();
        }
        return null;
    }

    private static synchronized CacheData registerNode(String expression) throws OgnlException {
        CacheData cacheData = CACHE.get(expression);
        if (cacheData != null) {
            return cacheData;
        }
        //替换label
        for (Map.Entry<String, String> entry : Label.getLabelMapper().entrySet()) {
            expression = expression.replace(entry.getKey(), entry.getValue());
        }
        SimpleNode node = (SimpleNode) Ognl.parseExpression(expression);
        cacheData = new CacheData();
        cacheData.setExpression(expression);
        cacheData.setNode(node);
        CACHE.put(expression, cacheData);
        return cacheData;
    }

    public static class CacheData {

        private String expression;
        private Node node;

        public String getExpression() {
            return expression;
        }

        public void setExpression(String expression) {
            this.expression = expression;
        }

        public Node getNode() {
            return node;
        }

        public void setNode(Node node) {
            this.node = node;
        }

        @Override
        public String toString() {
            return expression;
        }
    }
}
